﻿#ifndef PAGE_H
#define PAGE_H

#include "perf.h"
#include <fstream>
#include <map>
#include <thread>

using x86_Page = uint64_t;
using RISC_Page = uint64_t;

enum class PageType
{
	X86 = 1,
	RISC = 2,
	X86_OPT = 5,
	RISC_OPT = 6
};
enum class x86_PState : uint64_t
{
	Present = (1 << 0),
	RW = (1 << 1),
	User = (1 << 2),
	PWT = (1 << 3),
	PCD = (1 << 4),
	Accessed = (1 << 5),
	PageSize = (1 << 7),
	R = (1 << 11),
	NE = (uint64_t)1 << 63
};
enum class RISC_PState : uint64_t
{
	Valid = (1 << 0),
	Read = (1 << 1),
	Write = (1 << 2),
	Execute = (1 << 3),
	User = (1 << 4),
	Global = (1 << 5),
	Accessed = (1 << 6),
	Dirty = (1 << 7),
};
enum class PageLevel : uint64_t
{
	Level1 = (uint64_t)0 << 60,
	Level2 = (uint64_t)1 << 60,
	Level3 = (uint64_t)2 << 60,
	Level4 = (uint64_t)3 << 60,
};

enum class TLB_State : uint8_t
	// TLB时钟信号
{
	IDLE = 0,       // 空闲
	SPLIT = 1,      // 拆分地址
	L1_SEARCH = 2,  // L1查找
	L2_SEARCH = 3,  // L2查找
	SWAP = 4,       // 交换
	PTE_IDX = 5,    // 确定PTE索引
	PTE_LDR = 6,    // 加载PTE
	PTE_VIF = 7,    // 确定PTE有效性
	CONCAT = 8,     // 拼接物理地址
	CHK_LEV = 16,   // 确定开始遍历的层次
	ERROR = 255     // 错误
};

class TLB
{
public:
	Perf p;
	//split:0=1G,1=2M,2=4K
	std::pair<uint64_t, uint64_t> split[3];  //<VPNF,Offset>
	std::pair<uint16_t, uint8_t> swap_val;//<index,tlb_idx>
	uint64_t address;
	uint64_t tmp_address;
	uint64_t tmp_var;//if found:L1/L2 PTE;else:Memory PTE
	uint16_t idx[4];
	bool valid[3];  // identify which level is valid
	uint8_t level;
	uint8_t access;
	TLB_State status;
    TLB() : status(TLB_State::IDLE), level(-1), access(0) {}
	~TLB() = default;
	void setup(uint64_t addr, uint8_t access)  // 设置TLB
	{
		while (status != TLB_State::IDLE);
		address = addr;
		this->access = access;
		status = TLB_State::SPLIT;
	}
	const TLB_State getStatus() const { return status; }
};

#endif